package ca.etsmtl.log430.lab1;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PipedWriter;

/**************************************************************************************
 ** Class name: MainFilter Original author: A.J. Lattanze, CMU Date: 12/3/99
 ** Version 1.0
 ** 
 ** Adapted by R. Champagne, Ecole de technologie superieure 2002-May-08,
 ** 2011-Jan-12.
 ** 
 *************************************************************************************** 
 ** Purpose: Assignment 1 for LOG430, Architecture logicielle. This assignment is
 ** designed to illustrate a pipe and filter architecture. For the instructions,
 ** refer to the assignment write-up.
 ** 
 ** Abstract: This class contains the main method for assignment 1. The
 ** assignment 1 program consists of 5 files:
 ** 
 ** 1) MainFilter: starts all filters, reads each student entry from the input file
 **    and sends it to its output stream.
 ** 2) ProgramFilter: separates the LOG students from CGL students and writes them to
 **    the appropriate output pipe.
 ** 3) CourseFilter: determines if a student entry has taken a particular course that
 **    is specified during instantiation.
 ** 4) MergeFilter: accepts input from 2 input pipes and writes it to its output pipe.
 ** 5) FileWriterFilter: sends its input stream to a text file.
 ** 
 ** Pseudo Code:
 ** 
 ** start ProgramFilter
 ** start CourseFilter for LOG120
 ** start CourseFilter for CGL200
 ** start MergeFilter
 ** start FileWriterFilter
 ** 
 ** open input file provided on command line
 ** 
 ** while not eof (input file)
 **    read line of text
 **    write line of text to output pipe 
 ** end while
 ** 
 ** close pipes and files
 ** 
 ** Running the program
 ** 
 ** Java MainFilter IputFile OutputFile > ListingFile
 ** 
 ** MainFilter - Program name
 ** InputFile - Text input file (see comments below)
 ** OutputFile - Text output file with students
 ** ListingFile - Optional file to direct debug statements
 ** 
 ** Modification Log
 ************************************************************************************** 
 ** 
 **************************************************************************************/

public class MainFilter {

	public static void main(String argv[]) {
		// Lets make sure that input and output files are provided on the
		// command line

		if (argv.length != 3) {

			System.out
					.println("\n\nNombre incorrect de parametres d'entree. Utilisation:");
			System.out
					.println("\njava MainFilter <fichier d'entree> <fichier de sortie success> <fichier de sortie fail>");

		} else {

			// Declarations:

			String LineOfText;
			File InputFile = new File(argv[0]);

			// These are the declarations for the pipes.
			PipedWriter pipeMainFilterToProgramFilter = new PipedWriter();
			PipedWriter pipeProgramFilterToLog320Filter = new PipedWriter();
			PipedWriter pipeProgramFilterToCGL200Filter = new PipedWriter();
			PipedWriter pipeLog320FilterToMergeFilterSuccess = new PipedWriter();
			PipedWriter pipeCGL200ToMergeFilterSuccess = new PipedWriter();
			
			//sysB pipes
			PipedWriter pipeMAT210ToMAT205Success = new PipedWriter();
			PipedWriter pipeMAT205ToSuccessFilter = new PipedWriter();
			PipedWriter pipeMAT205ToFailFilter = new PipedWriter();
			
			PipedWriter pipeLOG120ToMAT210Filter = new PipedWriter();
			
			PipedWriter pipeCGL110ToFailFilter = new PipedWriter();
			PipedWriter pipeCGL110ToMath210Filter = new PipedWriter();
			
			
			//sysA fct 2.
			PipedWriter pipeLog320FilterToMergeFilterFail = new PipedWriter();
			PipedWriter pipeCGL200ToMergeFilterFail = new PipedWriter();
			
			PipedWriter pipeMergeFilterSuccessToFileWriterFilterSuccess = new PipedWriter();
			PipedWriter pipeMergeFilterFailToFileWriterFilterFail = new PipedWriter();
			
			// Instantiate the Program Filter Thread
			Thread ProgramFilter1 = new ProgramFilter(pipeMainFilterToProgramFilter, pipeProgramFilterToLog320Filter, pipeProgramFilterToCGL200Filter);

			// Instantiate the Course Filter Threads
			Thread CourseFilter1 = new CourseFilter("LOG120", pipeProgramFilterToLog320Filter, pipeLOG120ToMAT210Filter, pipeLog320FilterToMergeFilterFail);
			Thread CourseFilter2 = new CourseFilter("CGL200", pipeProgramFilterToCGL200Filter, pipeCGL200ToMergeFilterSuccess, pipeCGL200ToMergeFilterFail);

			//3 nouveau filter de cours
			Thread CourseFilter3 = new CourseFilter("MAT210", pipeProgramFilterToLog320Filter, pipeLog320FilterToMergeFilterSuccess, pipeLog320FilterToMergeFilterFail);
			Thread CourseFilter4 = new CourseFilter("MAT205", pipeProgramFilterToLog320Filter, pipeLog320FilterToMergeFilterSuccess, pipeLog320FilterToMergeFilterFail);
			Thread CourseFilter5 = new CourseFilter("CGL110", pipeProgramFilterToLog320Filter, pipeLog320FilterToMergeFilterSuccess, pipeLog320FilterToMergeFilterFail);

			// Instantiate the Merge Filter Thread
			Thread MergeFilterSuccess = new MergeFilter(pipeLog320FilterToMergeFilterSuccess, pipeCGL200ToMergeFilterSuccess, pipeMergeFilterSuccessToFileWriterFilterSuccess);
			Thread MergeFilterFail = new MergeFilter(pipeLog320FilterToMergeFilterFail, pipeCGL200ToMergeFilterFail, pipeMergeFilterFailToFileWriterFilterFail);

			// Instantiate the FileWriter Filter Thread
			Thread FileWriterFilterSuccess = new FileWriterFilter(argv[1], pipeMergeFilterSuccessToFileWriterFilterSuccess);
			Thread FileWriterFilterFail = new FileWriterFilter(argv[2], pipeMergeFilterFailToFileWriterFilterFail);
			
			// Start the threads (these are the filters)
			ProgramFilter1.start();
			
			CourseFilter1.start();
			CourseFilter2.start();
			
			MergeFilterSuccess.start();
			MergeFilterFail.start();
			
			FileWriterFilterSuccess.start();
			FileWriterFilterFail.start();

			// Open input file. The input file is a field oriented and
			// space-separated.
			// The fields are as follows:
			//
			// Student ID Student's Program Course numbers that the student
			// Last Name Acronym has completed with no hyphens
			//
			// Here is an example:
			//
			// FRAE230679 Franklin LOG LOG120 MAT115 CHM100 COM110

			// Check to ensure that the file exists

			if (!InputFile.exists()) {

				System.out.println("\nMainFilter:: file "
						+ InputFile.getAbsolutePath() + " does not exist.");

			} else {

				System.out.println("MainFilter:: file "
						+ InputFile.getAbsolutePath() + " opened.");

				try {
					// Create a buffered reader the file
					BufferedReader InFile = new BufferedReader(
							new InputStreamReader(new FileInputStream(
									(InputFile))));

					// Read each line of text

					boolean Done = false;

					while (!Done) {

						// Read a line of text from the input file and convert
						// it to upper case

						LineOfText = InFile.readLine();

						if (LineOfText == null) {

							Done = true;

						} else {

							LineOfText.toUpperCase();

							System.out.println("MainFilter:: read: "
									+ LineOfText);

							try {

								// write line of text to the pipe
								pipeMainFilterToProgramFilter.write(LineOfText, 0, LineOfText.length());
								pipeMainFilterToProgramFilter.write((int) '\n');
								// signals end of line
								pipeMainFilterToProgramFilter.flush();
								System.out.println("MainFilter:: wrote: "
										+ LineOfText + " to output pipe.");

							} catch (Exception Error) {

								System.out
										.println("MainFilter:: Error writing to pipe01.");
							} // try/catch

						} // if

					} // while

					// Close the input file

					InFile.close();
					System.out.println("\nMainFilter:: closing "
							+ InputFile.getAbsolutePath());

				} // try

				catch (Exception Error) {

					System.out
							.println("MainFilter:: Unable to create file stream");

				} // catch

			} // if

			try {

				pipeMainFilterToProgramFilter.close();
				System.out.println("MainFilter:: output pipe closed.");

			} catch (Exception Error) {

				System.out.println("MainFilter:: Error closing pipes.");

			} // try/catch

		} // if

	} // main

} // MainFilter